; A label, used for counting frames and setting smooth scroll.
scroll_pos	= $0340

; Set assembly point - $0900 (2304) for the program.
		* = $0900

; Switch off the system interrupts ('cos this is runtime code).
		sei

; Clear the screen RAM and set the colour map.
		ldx #$00
screen_clear	lda #$20
		sta $0400,x
		sta $0500,x
		sta $0600,x
		sta $06e8,x
		lda #$0e
		sta $d800,x
		sta $d900,x
		sta $da00,x
		sta $dae8,x
		inx
		bne screen_clear

; Reset the scrolltext to the start.
		jsr reset_scroll

; The main loop - first wait for the raster to reach $FC.
main_loop	lda #$fc
		cmp $d012
		bne main_loop

; Little timer to make sure it only happens once a frame...
		ldx #$10
delay		dex
		bne delay

; Read scroll_pos, add one and if it gets to 4 it's time to move.
		ldx scroll_pos
		inx
		cpx #$04
		bne scroll_pos_xb

; Move the data for the scroller.
		ldx #$00
move_scroll	lda $0401,x
		sta $0400,x
		inx
		cpx #$27
		bne move_scroll

; Read the next character and if it's $00 reset the scroller.
read_scroll	lda $1000
		bne ok
		jsr reset_scroll
		jmp read_scroll

; Write the character to the screen at the right.
ok		sta $0427

; Add one to the position in the text.
		inc read_scroll+$01
		bne no_highbyte
		inc read_scroll+$02

; Put a 0 into the X so that it resets scroll_pos
no_highbyte	ldx #$00

; Write back to scroll_pos - if it wasn't 4 this is where we branched
; to.
scroll_pos_xb	stx scroll_pos

; This is a "sneaky" bit to get the $D016 value - transfer the X to
; the A, multiply by two with an ASL and exclusive OR by 7 to reverse
; the value before writing to $D016.

		txa
		asl
		eor #$07
		sta $d016

; Finally, back to the main loop.
		jmp main_loop

; This subroutine resets the scroller to $1000.
reset_scroll	lda #$00
		sta read_scroll+$01
		lda #$10
		sta read_scroll+$02
		rts

; Change assembly point to $1000 (4096)
		*=$1000

; And here's the scrolltext.
message		.scrl "wheee!!  one line scrollers are cool!        "
		.byte $00